package com.fxsen.platform.web.controllers;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fxsen.commons.cache.util.RedisUtils;
import com.fxsen.commons.core.annotation.RecordLog;
import com.fxsen.commons.core.annotation.NotTokenRequired;
import com.fxsen.commons.core.base.common.OnlineUser;
import com.fxsen.commons.core.base.result.ResponseResult;
import com.fxsen.commons.utils.Md5Utils;
import com.fxsen.commons.sysmanager.core.entity.User;
import com.fxsen.commons.sysmanager.core.entity.bo.LoginBo;
import com.fxsen.commons.sysmanager.core.service.IOperationLogService;
import com.fxsen.commons.sysmanager.core.service.IUserService;
import com.fxsen.commons.core.exception.BusinessException;
import com.fxsen.commons.web.core.util.JwtUtils;
import com.fxsen.commons.utils.SessionUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author fxsen
 */
@RestController
@Api(tags = "系统：登录接口")
@RequestMapping("/login")
public class LoginController {
	@Autowired
	private IOperationLogService operationLogService;
	@Autowired
	private IUserService userService;
	@Autowired
	private RedisUtils redisUtils;
	/**
	 * 是否开启账户锁定策略
	 */
	@Value("${project-config.account.lock:false}")
	private boolean accountLock;
	/**
	 * 密码输入多少次锁定
	 */
	@Value("${project-config.account.lock-frequency:3}")
	private int lockFrequency;
	/**
	 * 锁定时间
	 */
	@Value("${project-config.account.lock-time:900}")
	private int lockTime;

	@ApiOperation(value = "登录")
	@PostMapping(value = "/doLogin")
	@NotTokenRequired
	@RecordLog("登录")
	public ResponseResult doLogin(@RequestBody LoginBo loginBo, HttpServletRequest request) {
		if (null == loginBo || StringUtils.isBlank(loginBo.getLoginName())){
			throw new BusinessException("未传请求参数！");
		}
		//错误次数key
		String errorKey = this.getClass().getName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName()
				+":"+loginBo.getLoginName()+ "_errorNum";
		//账户锁定key
		String lockKey = this.getClass().getName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName()
				+":"+loginBo.getLoginName() + "_lock";
		int errorNum = 0;
		//开起账户锁定策略
		if (accountLock){
			//从redis拿取错误次数
			if (redisUtils.hasKey(errorKey)){
				errorNum = (int)redisUtils.get(errorKey);
			}
			boolean lock = false;
			//从redis拿取锁定状态
			if (redisUtils.hasKey(lockKey)){
				lock = (boolean)redisUtils.get(lockKey);
			}
			if (lock){
				throw new BusinessException("密码连续错误"+lockFrequency+"次，账号被锁定，请"+lockTime/60+"分钟后后再试。");
			}
			if (errorNum >= lockFrequency){
				//锁定该账号
				redisUtils.set(lockKey,true,lockTime);
				throw new BusinessException("密码连续错误"+lockFrequency+"次，账号被锁定，请"+lockTime/60+"分钟后后再试。");
			}
		}
		String uid = loginBo.getUid();
		String captcha = loginBo.getCaptcha();
		if (StringUtils.isBlank(uid) || StringUtils.isBlank(captcha)){
			throw new BusinessException("验证码错误或已失效！");
		}
		Object object = redisUtils.get("captcha_" + uid);
		if (object == null || StringUtils.isBlank(object.toString()) || !StringUtils.equalsIgnoreCase(captcha,object.toString())){
			throw new BusinessException("验证码错误或已失效！");
		}
		redisUtils.del("captcha_"+uid);
		LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(User::getLoginName,loginBo.getLoginName());
		User user = userService.getOne(queryWrapper);
		if (user == null || !Md5Utils.digest(loginBo.getPassword()).equals(user.getPassword())) {
			if (accountLock){
				//错误次数存入缓存，有效期一分钟
				redisUtils.set(errorKey,errorNum + 1,60);
			}
			throw new BusinessException("用户名或密码错误！");
		}
		//给分配一个token 然后返回
		String jwtToken = JwtUtils.createToken(user.getId(),user.getUserName(),user.getLoginName());
		//通过验证
		OnlineUser onlineUser = new OnlineUser(jwtToken, user.getId(), user.getUserName(), user.getLoginName());
		SessionUtils.onLogin(onlineUser,request);
		//存到redis
		redisUtils.set(JwtUtils.JWT_TOKEN_HEADER+"_"+user.getId(),jwtToken,30*60);
		return ResponseResult.success(onlineUser);
	}
	@ApiOperation(value = "退出登录")
	@PostMapping(value = "/doLogOut")
	@NotTokenRequired
	@RecordLog("登出")
	public void doLogOut(HttpServletRequest request) {
		String token = request.getHeader(JwtUtils.JWT_TOKEN_HEADER);
		if (StringUtils.isNotBlank(token)){
			String userId = JwtUtils.getAudience(token);
			if (redisUtils.hasKey(JwtUtils.JWT_TOKEN_HEADER + "_" + userId)){
				redisUtils.del(JwtUtils.JWT_TOKEN_HEADER + "_" + userId);
				String userName = JwtUtils.getClaimByName(token, "loginName").asString();
				String realName = JwtUtils.getClaimByName(token, "username").asString();
			}
		}
		SessionUtils.logOut(request);
	}
	@ApiOperation(value = "获取验证码")
	@GetMapping(value = "/getCaptcha")
	@NotTokenRequired
	public ResponseResult getCaptcha(){
		try {
			// 定义图形验证码的长、宽、验证码字符数、干扰线宽度
			LineCaptcha captcha = CaptchaUtil.createLineCaptcha(122, 38, 4, 3);
			//CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(118, 38 ,4, 2);
			captcha.setBackground(Color.getColor("#2E2E2E"));
			String code = captcha.getCode();
			String key = IdUtil.simpleUUID();
			String imageBase64 = captcha.getImageBase64Data();
			Map<String, String> map = new HashMap<>(16);
			map.put("key", key);
			map.put("img", imageBase64);
			redisUtils.set("captcha_"+key,code,5 * 60);
			return ResponseResult.success(map);
		}catch (Exception e){
			e.printStackTrace();
			return ResponseResult.failed();
		}
	}
	public static void main(String[] args){
		System.out.println(Md5Utils.digest("123456"));
	}
}
